﻿using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using MIAP.Entidades.TiposXML;
using MIAP.Negocio.Properties;

namespace MIAP.Negocio.Utiles
{
    public class TxtHandling
    {
        #region variables
        /// <summary>
        /// numero de columnas que tendra el archivo txt
        /// </summary>
        private int _noColumnas;

        /// <summary>
        /// 
        /// </summary>
        private List<ColumnaBase> _datosColumnas;
        /// <summary>
        /// Separador de las columnas del archivo txt
        /// </summary>
        private string _separadorColumnas;

        /// <summary>
        /// Xml con el cual validaremos el excel
        /// </summary>
        private LecturaXML _lecturaXml;

        /// <summary>
        /// stream en del archivo
        /// </summary>
        private Stream _archivoTexto;

        /// <summary>
        /// errores presentados del sistema
        /// </summary>
        private StringBuilder _errores;

        #endregion

        #region Propiedades
        /// <summary>
        /// Errores ocasionados en la verificación del archivo
        /// </summary>
        public string Errores
        {
            get { return _errores.ToString(); }
        }

        #endregion

        #region constructor

        public TxtHandling(Stream streamtxt, string stringXml)
        {
            this._lecturaXml = new LecturaXML(stringXml);
            this._archivoTexto = streamtxt;
            this._separadorColumnas = this._lecturaXml.ObtenValorAtributoTextSeparador();
            this._datosColumnas = this._lecturaXml.ObtenerValorColumnasTextoXML();
            this._noColumnas = this._datosColumnas.Count;
            this._errores = new StringBuilder();
        }

        /// <summary>
        /// Regresa el contenido del excel el un dataset
        /// </summary>
        /// <returns>regresa un dataset con el contenido del txt, o null si existio algun error (obtener variable de error)</returns>
        public DataSet ConvertToDataSet()
        {
            var dataSet1 = new DataSet(@"ArchivoTexto");
            var dt = new DataTable();
            
            for (var i = 0; i < this._noColumnas; i++)
            {
                dt.Columns.Add("Columna " + (i+1));
            }

            using (var reader= new StreamReader(this._archivoTexto))
            {
                var linea=reader.ReadLine();
                if (linea == null)
                {
                    this._errores.AppendLine(Strings.ExcelVacio);
                    return null;
                }
                var noLinea = 1;
                while (linea != null)
                {
                    var split = linea.Split(new[]{ this._separadorColumnas},StringSplitOptions.None);
                    var dr = dt.NewRow();
                    if (split.Count() != this._noColumnas)
                    {
                        this._errores.AppendLine(string.Format(Strings.ErrorNumeroColTexto,noLinea,this._noColumnas));                        
                    }

                    for (var i = 0; i < this._noColumnas; i++)
                    {
                        var valor=split[i].Replace("|", string.Empty);
                        if (!this.ValidaTipoDato(this._datosColumnas[i], valor))
                        {
                            this._errores.AppendLine(String.Format(Strings.ErrorTipoTexto, i+1, noLinea,
                                                                   this._datosColumnas[i].TipoVariable));
                        }
                        else
                        {
                            dr[i] = valor;
                        }                        
                    }
                    dt.Rows.Add(dr);
                    noLinea++;
                    linea = reader.ReadLine();
                }
            }    
            dataSet1.Tables.Add(dt);
            return String.IsNullOrEmpty(this.Errores)? dataSet1:null;
        }

        /// <summary>
        /// cierra correctamente el stream del archivo txt
        /// </summary>
        public void Close()
        {
            this._archivoTexto.Close();
        }

        /// <summary>
        /// Varifica el tipo de dato del valor enviado
        /// </summary>
        /// <param name="columna"></param>
        /// <param name="valor"></param>
        /// <returns></returns>
        private bool ValidaTipoDato(ColumnaBase columna,string valor)
        {
            bool esValido ;
            switch (columna.TipoVariable)
            {
                    case TipoVariable.Boolean:
                    var intetnoBool = false;
                    esValido= bool.TryParse(valor, out intetnoBool );
                    break;
                case TipoVariable.Numeric:
                    Double intentoNum;
                    esValido = Double.TryParse(valor, out intentoNum);
                    break;
                default:
                    esValido = true;
                    break;
            }

            return esValido;
        }

        #endregion
    }
}
